using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Text;
using SumerCoreDevOps.Domain.Entities;
using SumerCoreDevOps.Infrastructure.Data;
using SumerCoreDevOps.Infrastructure.Security;

namespace SumerCoreDevOps.Infrastructure.ImageManagement;

/// <summary>
/// Docker 镜像构建和推送服务
/// </summary>
public class DockerImageService
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly ILogger<DockerImageService> _logger;
    private readonly ImageTagRuleManager _tagRuleManager;

    public DockerImageService(
        FreeSQLProvider dbProvider,
        ImageTagRuleManager tagRuleManager,
        ILogger<DockerImageService> logger)
    {
        _dbProvider = dbProvider;
        _tagRuleManager = tagRuleManager;
        _logger = logger;
    }

    /// <summary>
    /// 构建 Docker 镜像
    /// </summary>
    public async Task<BuildImageResult> BuildImageAsync(
        string dockerfilePath,
        string contextPath,
        string imageTag,
        Dictionary<string, string>? buildArgs = null,
        CancellationToken cancellationToken = default)
    {
        var result = new BuildImageResult();
        var startTime = DateTime.UtcNow;

        try
        {
            _logger.LogInformation("开始构建 Docker 镜像: {ImageTag}", imageTag);

            // 构建 docker build 命令
            var arguments = new StringBuilder($"build -t {imageTag}");

            // 添加构建参数
            if (buildArgs != null)
            {
                foreach (var arg in buildArgs)
                {
                    arguments.Append($" --build-arg {arg.Key}={arg.Value}");
                }
            }

            arguments.Append($" -f {dockerfilePath} {contextPath}");

            // 执行构建命令
            var processInfo = new ProcessStartInfo
            {
                FileName = "docker",
                Arguments = arguments.ToString(),
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using var process = Process.Start(processInfo);
            if (process == null)
            {
                throw new InvalidOperationException("无法启动 docker 进程");
            }

            var output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
            var error = await process.StandardError.ReadToEndAsync(cancellationToken);
            await process.WaitForExitAsync(cancellationToken);

            result.Success = process.ExitCode == 0;
            result.Output = output;
            result.ErrorMessage = error;
            result.ImageTag = imageTag;
            result.DurationSeconds = (int)(DateTime.UtcNow - startTime).TotalSeconds;

            if (result.Success)
            {
                _logger.LogInformation("Docker 镜像构建成功: {ImageTag}, 耗时: {Duration}秒",
                    imageTag, result.DurationSeconds);

                // 获取镜像信息
                await GetImageInfoAsync(imageTag, result, cancellationToken);
            }
            else
            {
                _logger.LogError("Docker 镜像构建失败: {ImageTag}, 错误: {Error}", imageTag, error);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "构建 Docker 镜像时发生异常: {ImageTag}", imageTag);
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }

    /// <summary>
    /// 推送 Docker 镜像到仓库
    /// </summary>
    public async Task<PushImageResult> PushImageAsync(
        string imageTag,
        DockerRegistry registry,
        CancellationToken cancellationToken = default)
    {
        var result = new PushImageResult();
        var startTime = DateTime.UtcNow;
        var retryCount = 0;

        try
        {
            _logger.LogInformation("开始推送 Docker 镜像: {ImageTag} 到 {Registry}",
                imageTag, registry.RegistryUrl);

            // 登录到仓库
            var loginSuccess = await LoginToRegistryAsync(registry, cancellationToken);
            if (!loginSuccess)
            {
                result.Success = false;
                result.ErrorMessage = "登录到 Docker 仓库失败";
                return result;
            }

            // 推送镜像（带重试机制）
            while (retryCount < registry.MaxRetries)
            {
                result = await ExecutePushAsync(imageTag, cancellationToken);

                if (result.Success)
                {
                    break;
                }

                retryCount++;
                if (retryCount < registry.MaxRetries)
                {
                    // 指数退避
                    var delay = registry.RetryIntervalSeconds * (int)Math.Pow(2, retryCount - 1);
                    _logger.LogWarning("推送失败，{Delay}秒后进行第 {Retry} 次重试", delay, retryCount);
                    await Task.Delay(delay * 1000, cancellationToken);
                }
            }

            // 验证镜像
            if (result.Success)
            {
                result.Success = await VerifyImageAsync(imageTag, registry, cancellationToken);
                if (!result.Success)
                {
                    result.ErrorMessage = "镜像推送后验证失败";
                }
            }

            // 登出
            await LogoutFromRegistryAsync(registry, cancellationToken);

            result.DurationSeconds = (int)(DateTime.UtcNow - startTime).TotalSeconds;
            result.RetryCount = retryCount;

            if (result.Success)
            {
                _logger.LogInformation("Docker 镜像推送成功: {ImageTag}, 重试次数: {RetryCount}, 耗时: {Duration}秒",
                    imageTag, retryCount, result.DurationSeconds);
            }
            else
            {
                _logger.LogError("Docker 镜像推送失败: {ImageTag}, 已重试 {RetryCount} 次", imageTag, retryCount);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "推送 Docker 镜像时发生异常: {ImageTag}", imageTag);
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }

    /// <summary>
    /// 登录到 Docker 仓库
    /// </summary>
    private async Task<bool> LoginToRegistryAsync(DockerRegistry registry, CancellationToken cancellationToken)
    {
        try
        {
            // 解密密码
            var password = DecryptPassword(registry.EncryptedPassword ?? "");

            var processInfo = new ProcessStartInfo
            {
                FileName = "docker",
                Arguments = $"login {registry.RegistryUrl} -u {registry.Username} --password-stdin",
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using var process = Process.Start(processInfo);
            if (process == null) return false;

            await process.StandardInput.WriteLineAsync(password);
            await process.StandardInput.FlushAsync(cancellationToken);
            process.StandardInput.Close();

            await process.WaitForExitAsync(cancellationToken);
            return process.ExitCode == 0;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "登录 Docker 仓库失败: {Registry}", registry.RegistryUrl);
            return false;
        }
    }

    /// <summary>
    /// 登出 Docker 仓库
    /// </summary>
    private async Task LogoutFromRegistryAsync(DockerRegistry registry, CancellationToken cancellationToken)
    {
        try
        {
            var processInfo = new ProcessStartInfo
            {
                FileName = "docker",
                Arguments = $"logout {registry.RegistryUrl}",
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using var process = Process.Start(processInfo);
            if (process != null)
            {
                await process.WaitForExitAsync(cancellationToken);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "登出 Docker 仓库时发生错误: {Registry}", registry.RegistryUrl);
        }
    }

    /// <summary>
    /// 执行推送操作
    /// </summary>
    private async Task<PushImageResult> ExecutePushAsync(string imageTag, CancellationToken cancellationToken)
    {
        var result = new PushImageResult { ImageTag = imageTag };

        var processInfo = new ProcessStartInfo
        {
            FileName = "docker",
            Arguments = $"push {imageTag}",
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using var process = Process.Start(processInfo);
        if (process == null)
        {
            result.ErrorMessage = "无法启动 docker push 进程";
            return result;
        }

        var output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
        var error = await process.StandardError.ReadToEndAsync(cancellationToken);
        await process.WaitForExitAsync(cancellationToken);

        result.Success = process.ExitCode == 0;
        result.Output = output;
        result.ErrorMessage = error;

        return result;
    }

    /// <summary>
    /// 验证镜像是否成功推送
    /// </summary>
    private async Task<bool> VerifyImageAsync(string imageTag, DockerRegistry registry, CancellationToken cancellationToken)
    {
        try
        {
            // 尝试 pull 镜像来验证（不实际下载，只检查 manifest）
            var processInfo = new ProcessStartInfo
            {
                FileName = "docker",
                Arguments = $"manifest inspect {imageTag}",
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using var process = Process.Start(processInfo);
            if (process == null) return false;

            await process.WaitForExitAsync(cancellationToken);
            return process.ExitCode == 0;
        }
        catch
        {
            return false;
        }
    }

    /// <summary>
    /// 获取镜像信息
    /// </summary>
    private async Task GetImageInfoAsync(string imageTag, BuildImageResult result, CancellationToken cancellationToken)
    {
        try
        {
            var processInfo = new ProcessStartInfo
            {
                FileName = "docker",
                Arguments = $"inspect {imageTag} --format=\"{{{{.Id}}}} {{{{.Size}}}}\"",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using var process = Process.Start(processInfo);
            if (process == null) return;

            var output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
            await process.WaitForExitAsync(cancellationToken);

            if (process.ExitCode == 0)
            {
                var parts = output.Trim().Split(' ');
                if (parts.Length >= 2)
                {
                    result.ImageId = parts[0];
                    if (long.TryParse(parts[1], out var size))
                    {
                        result.ImageSize = size;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "获取镜像信息失败: {ImageTag}", imageTag);
        }
    }

    /// <summary>
    /// 解密密码（使用 AES-256 加密）
    /// </summary>
    private string DecryptPassword(string encryptedPassword)
    {
        if (string.IsNullOrEmpty(encryptedPassword))
            return string.Empty;

        try
        {
            // 使用 EncryptionHelper 解密
            return EncryptionHelper.Decrypt(encryptedPassword);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "解密密码失败");
            // 如果解密失败，可能是明文存储，直接返回
            // 生产环境应该抛出异常而不是降级处理
            return encryptedPassword;
        }
    }
}

/// <summary>
/// 镜像构建结果
/// </summary>
public class BuildImageResult
{
    public bool Success { get; set; }
    public string? ImageTag { get; set; }
    public string? ImageId { get; set; }
    public long? ImageSize { get; set; }
    public string? Output { get; set; }
    public string? ErrorMessage { get; set; }
    public int DurationSeconds { get; set; }
}

/// <summary>
/// 镜像推送结果
/// </summary>
public class PushImageResult
{
    public bool Success { get; set; }
    public string? ImageTag { get; set; }
    public string? Output { get; set; }
    public string? ErrorMessage { get; set; }
    public int DurationSeconds { get; set; }
    public int RetryCount { get; set; }
}
